﻿using System;
using System.Collections.Generic;
using System.Linq;



public partial class User : ISerialize
{
    private long m_Id;
    /// <summary>
    /// id
    /// </summary>
    public long id { get { return m_Id; } }

    private string m_Nick = "";
    /// <summary>
    /// 昵称
    /// </summary>
    public string nick { get { return m_Nick; } }

    public string name => m_Nick;

    private string m_Token = "";
    /// <summary>
    /// 用于断线重连
    /// </summary>
    public string token { get { return m_Token; } }

    /// <summary>
    /// 普通的货币
    /// </summary>
    private int m_Coin;
    public int coin { get { return m_Coin; } }

    /// <summary>
    /// 付费的货币
    /// </summary>
    private int m_Diamond;
    public int diamond { get { return m_Diamond; } }


    /// <summary>
    /// 充值次数
    /// </summary>
    int m_ChargedTimes;
    public bool hasCharged => m_ChargedTimes > 0;

    /// <summary>
    /// home界面广告播放次数
    /// </summary>
    private int m_HomeAdTimesRemain;
    public int homeAdTimesRemain
    {
        get { return m_HomeAdTimesRemain; }
        set { m_HomeAdTimesRemain = value; }
    }

    /// <summary>
    /// 等级
    /// </summary>
    private int m_Level;
    public int level => m_Level;

    /// <summary>
    /// 是否是机器人
    /// </summary>
    private bool m_IsRobot;
    public bool isRobot => m_IsRobot;

    /// <summary>
    /// 到达过的最大等级
    /// </summary>
    private int m_MaxLv;
    public int maxLv
    {
        get { return m_MaxLv; }
        set { m_MaxLv = value; }
    }

    /// <summary>
    /// 登陆天数
    /// </summary>
    private int m_LoginedDay;
    public int loginedDay
    {
        get
        {
            if (m_LoginedDay < 0) m_LoginedDay = 1;
            return m_LoginedDay;
        }
    }

    /// <summary>
    /// 已领取的登陆奖励
    /// </summary>
    private List<int> m_ObtainLoginBonus;
    public List<int> obtainLoginBonus
    {
        get => m_ObtainLoginBonus;
    }

    public const int maxObtainLoginBonusDay = 30;

    /// <summary>
    /// 已获取分享奖励
    /// </summary>
    int m_ObtainShareReward;
    public int obtainShareReward
    {
        get => m_ObtainShareReward;
        set => m_ObtainShareReward = value;
    }

    private List<Moment> m_Moments = new List<Moment>();
    public List<Moment> moments { get => m_Moments; set => m_Moments = value; }

    protected long m_MemberTimeEndDate;
    public long memberTimeEndDate => m_MemberTimeEndDate;

    private int m_FreeApplyCount;
    public int freeApplyCount => m_FreeApplyCount;

    public int myApplyNum
    {
        get
        {
            int count = 0;
            for (int i = 0; i < applies.Count; i++)
            {
                if (applies[i].sourceUserId == this.id)
                    count++;
            }
            return count;
        }
    }

    private UserInfo m_UserInfo;
    public UserInfo userInfo => m_UserInfo;

    private List<Apply> m_Applys = new List<Apply>();
    public List<Apply> applies
    {
        get => m_Applys;
        set => m_Applys = value;
    }
    public int appliesCount => applies.Count;

    List<Chat> m_Chats = new List<Chat>();
    public List<Chat> chats 
    {
        get => m_Chats;
        set => m_Chats = value;
    }
    List<long> m_Friends = new List<long>();
    public List<long> friends => m_Friends;

    List<long> m_likes = new List<long>();
    public List<long> likes
    {
        get => m_likes;
        set => m_likes = value;
    }
    List<long> m_belikes = new List<long>();
    public List<long> belikes
    {
        get => m_belikes;
        set => m_belikes = value;
    }
    List<Visit> m_visitors = new List<Visit>();
    public List<Visit> visitors
    {
        get => m_visitors;
        set => m_visitors = value;
    }
    List<Visit> m_myVisits = new List<Visit>();
    public List<Visit> myVisits
    {
        get => m_myVisits;
        set => m_myVisits = value;
    }
    public List<long> myFollows = new List<long>();
    public List<long> followers = new List<long>();

    Requirement m_Requirement;
    public Requirement requirement => m_Requirement;

    public User()
    {
    }

    public static Action<int> onUpdateDiamond;

    public void UpdateDiamond(int diamond)
    {
        m_Diamond = diamond;

        onUpdateDiamond?.Invoke(diamond);
    }

    public Apply AddApply(long sourceUserId, long targetUserId, int result, string msg, string rejectMsg, long applyTime, long viewtime, long resultTime)
    {
        var apply = this.applies.Find(e => e.sourceUserId == sourceUserId && e.targetUserId == targetUserId);

        if (apply != null)
        {
            apply.result = result;
            apply.msg = msg;
            apply.rejectMsg = rejectMsg;
            apply.applyTime = applyTime;
            apply.viewTime = viewtime;
            apply.resultTime = resultTime;
            return apply;
        }
        else
        {
            var newApply = new Apply() { sourceUserId = sourceUserId, targetUserId = targetUserId, result = result, msg = msg, rejectMsg = rejectMsg, applyTime = applyTime, viewTime = viewtime, resultTime = resultTime };
            this.applies.Add(newApply);
            return newApply;
        }
    }

    public Chat AddDialogue(long fromUserId, long toUserId, Dialogue dialogue)
    {
        bool me = fromUserId == this.id;

        Chat chat = this.chats.Find(e => e.AreUser(fromUserId, toUserId));

        if (chat != null)
        {
            chat.dialogues = chat.dialogues.ArrayAdd<Dialogue>(dialogue);

            if (!me)
                chat.newMsgCount++;
            return chat;
        }
        else
        {
            chat = new Chat()
            {
                userId1 = fromUserId,
                userId2 = toUserId,
                dialogues = new[]
                {
                    dialogue
                },
                newMsgCount = me ? 0 : 1
            };
            this.chats.Add(chat);
            return chat;
        }
    }
    public void UpdateApply(Apply apply)
    {
        for (int i = 0; i < this.applies.Count; i++)
        {
            if (applies[i].sourceUserId == apply.sourceUserId && applies[i].targetUserId == apply.targetUserId)
                applies[i] = apply;
        }
    }
    public void AddFriend(long friend)
    {
        if (m_Friends == null)
            m_Friends = new List<long>();

        if (!this.m_Friends.Contains(friend))
            m_Friends.Add(friend);
    }
    public void AddMyFollow(long targetUser)
    {
        if (this.myFollows == null)
            myFollows = new List<long>();

        if (!this.myFollows.Contains(targetUser))
            myFollows.Add(targetUser);
    }
    public void RemoveMyFollow(long targetUser)
    {
        if (this.myFollows != null)
            myFollows.Remove(targetUser);
    }
    public void RemoveFollower(long targetUser)
    {
        if (this.followers != null)
            followers.Remove(targetUser);
    }
    public void AddFollower(long targetUser)
    {
        if (this.followers == null)
            followers = new List<long>();

        if (!this.followers.Contains(targetUser))
            followers.Add(targetUser);
    }
    public void UpdateRequire(Requirement requirement)
    {
        m_Requirement = requirement;
    }
    public void UpdateRequire(int minAge, int maxAge, int minHeight, int maxHeight, int minEdu, 
        byte sameLocation, byte sameHometown, byte onlyUnmarried)
    {
        if (m_Requirement == null)
            m_Requirement = new Requirement();

        m_Requirement.minAge = minAge;
        m_Requirement.maxAge = maxAge;
        m_Requirement.minHeight = minHeight;
        m_Requirement.maxHeight = maxHeight;
        m_Requirement.minEdu = minEdu;
        m_Requirement.sameLocation = sameLocation > 0 ? true : false;
        m_Requirement.sameHometown = sameHometown > 0 ? true : false;
        m_Requirement.onlyUnmarried = onlyUnmarried > 0 ? true : false;
    }

    public void AddMyVisit(Visit visit)
    {
        this.myVisits.Add(visit);
    }

    public void AddVisitor(Visit visit)
    {
        this.visitors.Add(visit);
    }
    public void AddLike(long toUserId)
    {
        if (this.m_likes == null)
            m_likes = new List<long>();

        if(!likes.Contains(toUserId))
            this.likes.Add(toUserId);
    }

    public void AddBeLike(long likeFromUserId)
    {
        if (this.m_belikes == null)
            m_belikes = new List<long>();

        if(!m_belikes.Contains(likeFromUserId))
            m_belikes.Add(likeFromUserId);
    }

    public void AddMoment(Moment moment)
    {
        if (this.m_Moments == null)
            m_Moments = new List<Moment>();

        m_Moments.Add(moment);
    }
}

public partial class Visit : ISerialize
{
    public long userId;
    public int gender;
    public string name;
    public int birthYear;
    public string locationCity;
    public int height;
    public string iconTex;
    public long lastVisitTime;
    public int totalVisitCount;

    public override string ToString()
    {
        return $"[userId:{userId}  lastVisitTime:{lastVisitTime}  count:{totalVisitCount}]";
    }
}